setClass("DBScanNonParamClusterAlg",contains="VNonParamClusterAlg",
		representation(
				.noisePercent="numeric"
		),
		prototype=prototype(
				.description="DB Scan non parametric Clustering algorithm class",
				.noisePercent=0.1
		),
		validity=function(.Object){
			if(.Object@.noisePercent <=0 || .Object@.noisePercent>1 ){
				stop("noise percent must be in [0,1)")
			}
		}
) 

#methods
#initialization method 
setMethod("initialize",
		signature="DBScanNonParamClusterAlg",
		function(.Object,indexObject,noisePercent =0.1,...){
			.Object <-callNextMethod(.Object,indexObject,...)
			.Object@.noisePercent <- noisePercent
			
			validObject(.Object)
			return(.Object)
		})


setMethod("clusterize",
		signature="DBScanNonParamClusterAlg",
		definition=function(.Object,inputSet,...){
			callNextMethod(.Object,inputSet,...)
			
		print("DBSCAN")
			
			bestScore <- -.Machine$double.xmax
			#default all points in one cluster
			bestClustering <- rep(1,nrow(inputSet$X))
			clustSeq <- genClusNumSeq(inputSet)
	
			clustList <-foreach(cnum = clustSeq)%dopar%{
				
				#estimate MinPts
				MinPts <- round( nrow( inputSet$X )/cnum )
				#estimate eps
				nns <- find_nn_k(inputSet$X,MinPts)
				dists <- as.matrix( dist(inputSet$X) )
				mkNN <- unlist(lapply( 1:nrow(nns), FUN=function(n){
									max(dists[n,nns[n,]])
								} ) )
				mkNN <- sort(mkNN,decreasing=TRUE)
				#choose eps
				eps <-mkNN[ round( nrow( inputSet$X )*.Object@.noisePercent ) ]
				
				clusters <- dbscan(inputSet$X,MinPts=MinPts,eps=eps)$cluster
				#print("CLUSTERS: ");print(clusters)
				
				#score clusters without noise points
				removedNoiseSet <- inputSet$X[clusters>0,,drop=FALSE]
				clustersN <- clusters[clusters>0]
				#socore obtained clusters
				score <- ScoreSet(.Object@.indexObject,list(X=removedNoiseSet),clustersN)
				if(is.na(score) || is.infinite(score)){score <- -.Machine$double.xmax}
				#print("SCORE: ")
				#print(score)
				list(Score=score,Clusters=clusters)
			}
			for( i in 1:length(clustList)){
				if(clustList[[i]]$Score > bestScore){
					bestScore <- clustList[[i]]$Score
					bestClustering <-clustList[[i]]$Clusters
				}
			}
			
			
			
			return(bestClustering)
		}
) 

